#include "pch.h"
#include "auto_list_test.h"

#include <boostext/container/container.hpp>
#include <boostext/container/auto_list.hpp>

using namespace boostext;

/// Test if the element at the given position equals
/// a certain value
#define ASSERT_EQUAL_ELEMENT(list, value, pos)	{_list::const_iterator list##it = list.begin(); std::advance(list##it, pos); \
												ASSERT_EQUAL(value, *list##it); \
												}

/// Test if the first sequence equals the second one
#define ASSERT_EQUAL_SEQUENCE(list, vec)	{_list::const_iterator list##it = list.begin(); _vector::const_iterator vec##it = vec.begin(); \
												ASSERT_EQUAL(vec.size(), list.size()); \
												while( vec##it != vec.end() ) \
												{ \
													ASSERT_EQUAL(*vec##it, *list##it); \
													++vec##it; \
													++list##it; \
												} \
											}




void auto_list_test::construction()
{
	typedef auto_list<int>   _list;

	// Create an empty list
	{
		_list list;
		ASSERT_EQUAL(0, list.size());
	}

	// Create a list with a specified size
	{
		// There should be 10 items in the list, we cannot however test their values: they are undefined
		_list list(10);
		ASSERT_EQUAL(10, list.size());

		// The list has to be filled, so both begin and end should point to different
		// positions in the list
		ASSERT(list.begin() != list.end());

		// Try to loop through the list and test if it looped exactly 10 times
		std::size_t i = 0;
		foreach(int n, list) {++i;}
		ASSERT_EQUAL(10, i);
	}

	// Create a list with a specified size and value
	{
		// There should be 20 items in the list
		_list list(20, 42);
		ASSERT_EQUAL(20, list.size());

		// The list contains elements, thus begin and end should point to different positions
		ASSERT(list.begin() != list.end());

		// Test the contents of the list
		std::size_t i = 0;
		foreach(int n, list)
		{
			// Every element in the list should equal 42
			ASSERT_EQUAL(42, n);
			++i;
		}
		// We should have looped 20 times
		ASSERT_EQUAL(20, i);
	}

	// Move-construction from another auto_list
	{
		_list list1(6,42);
		_list list2(list1);

		// list1 should be empty, list2 should now contain those elements
		ASSERT_EQUAL(0, list1.size());
		ASSERT_EQUAL(6, list2.size());

		// Every value in list2 should equal 42
		std::size_t i = 0;
		foreach(int n, list2)
		{
			ASSERT_EQUAL(42, n);
			++i;
		}
		// We should have looped 6 times
		ASSERT_EQUAL(6, i);
	}

	// Move-construction from a std::list
	{
		std::list<int> list1(12,42);
		_list list2(list1);

		// list1 should be empty, list2 should now contain those elements
		ASSERT_EQUAL(0, list1.size());
		ASSERT_EQUAL(12, list2.size());

		// Every value in list2 should equal 42
		std::size_t i = 0;
		foreach(int n, list2)
		{
			ASSERT_EQUAL(42, n);
			++i;
		}
		// We should have looped 12 times
		ASSERT_EQUAL(12, i);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void auto_list_test::assignment()
{
	typedef auto_list<int>   _list;
	typedef std::vector<int> _vector;

	// Assign a given number of values to the list (equal to the constructor)
	{
		_list list;
		list.assign(10, 100);
		ASSERT_EQUAL(10, list.size());
		foreach(int i, list)
		{
			ASSERT_EQUAL(100, i);
		}
	}

	// Assign a sequence to the list
	{
		_vector   vec;
		vec << 10 << 20 << 30 << 40 << 50;

		_list list;
		list.assign(vec.begin(), vec.end());

		ASSERT_EQUAL_SEQUENCE(list, vec);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void auto_list_test::insertion()
{
	typedef auto_list<int>   _list;
	typedef std::vector<int> _vector;

	// Insertion of single elements
	{
		_vector vec;
		vec << 10 << 20 << 30 << 40 << 50;

		_list list;
		list << 10 << 20 << 30 << 40 << 50;

		ASSERT_EQUAL_SEQUENCE(list, vec);

		// Insert an element in the beginning
		list.insert(list.begin(), -5);
		ASSERT_EQUAL_ELEMENT(list, -5, 0);

		// Insert an element somewhere in the list
		_list::const_iterator i = list.begin();
		std::advance(i, 2);
		list.insert(i, 42);

		ASSERT_EQUAL_ELEMENT(list, 42, 2);

		// Insert an element in the end
		list.insert(list.end(), 42);
		ASSERT_EQUAL_ELEMENT(list, 42, 7);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////




void auto_list_test::operator()()
{
	construction();
	assignment();
	insertion();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
